package com.alibaba.cloud.ai.example.manus.schedule.service;

import com.alibaba.cloud.ai.example.manus.schedule.entity.ScheduleJob;
import com.alibaba.cloud.ai.example.manus.schedule.enums.JobStatus;
import com.alibaba.cloud.ai.example.manus.schedule.repository.ScheduleJobRepository;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.quartz.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.Map;
import java.util.Optional;

@Service
@Transactional
public class DynamicSchedulerService {

    private static final Logger logger = LoggerFactory.getLogger(DynamicSchedulerService.class);

    @Autowired
    private Scheduler scheduler;

    @Autowired
    private ScheduleJobRepository scheduleJobRepository;

    @Autowired
    private ObjectMapper objectMapper;

    /**
     * 添加定时任务
     */
    public void addJob(ScheduleJob scheduleJob) throws Exception {
        // 检查任务是否已存在
        if (scheduleJobRepository.existsByJobNameAndJobGroup(scheduleJob.getJobName(), scheduleJob.getJobGroup())) {
            throw new RuntimeException("任务已存在: " + scheduleJob.getJobName());
        }

        // 验证Cron表达式
        if (!CronExpression.isValidExpression(scheduleJob.getCronExpression())) {
            throw new RuntimeException("无效的Cron表达式: " + scheduleJob.getCronExpression());
        }

        // 创建JobDetail
        JobDetail jobDetail = createJobDetail(scheduleJob);

        // 创建Trigger
        Trigger trigger = createTrigger(scheduleJob);

        // 添加到调度器
        scheduler.scheduleJob(jobDetail, trigger);

        // 保存到数据库
        scheduleJob.setStatus(JobStatus.ACTIVE);
        scheduleJobRepository.save(scheduleJob);

        logger.info("成功添加定时任务: {}.{}", scheduleJob.getJobGroup(), scheduleJob.getJobName());
    }

    /**
     * 更新定时任务
     */
    public void updateJob(ScheduleJob scheduleJob) throws Exception {
        Optional<ScheduleJob> existingJob = scheduleJobRepository.findById(scheduleJob.getId());
        if (!existingJob.isPresent()) {
            throw new RuntimeException("任务不存在: " + scheduleJob.getId());
        }

        ScheduleJob existing = existingJob.get();
        JobKey jobKey = new JobKey(existing.getJobName(), existing.getJobGroup());

        // 验证Cron表达式
        if (!CronExpression.isValidExpression(scheduleJob.getCronExpression())) {
            throw new RuntimeException("无效的Cron表达式: " + scheduleJob.getCronExpression());
        }

        // 删除原有任务
        scheduler.deleteJob(jobKey);

        // 更新任务信息
        existing.setCronExpression(scheduleJob.getCronExpression());
        existing.setJobData(scheduleJob.getJobData());
        existing.setDescription(scheduleJob.getDescription());

        // 重新创建任务
        JobDetail jobDetail = createJobDetail(existing);
        Trigger trigger = createTrigger(existing);

        scheduler.scheduleJob(jobDetail, trigger);
        scheduleJobRepository.save(existing);

        logger.info("成功更新定时任务: {}.{}", existing.getJobGroup(), existing.getJobName());
    }

    /**
     * 删除定时任务
     */
    public void deleteJob(Long jobId) throws Exception {
        Optional<ScheduleJob> job = scheduleJobRepository.findById(jobId);
        if (!job.isPresent()) {
            throw new RuntimeException("任务不存在: " + jobId);
        }

        ScheduleJob scheduleJob = job.get();
        JobKey jobKey = new JobKey(scheduleJob.getJobName(), scheduleJob.getJobGroup());

        // 从调度器删除
        scheduler.deleteJob(jobKey);

        // 标记为删除
        scheduleJob.setStatus(JobStatus.DELETED);
        scheduleJobRepository.save(scheduleJob);

        logger.info("成功删除定时任务: {}.{}", scheduleJob.getJobGroup(), scheduleJob.getJobName());
    }

    /**
     * 暂停定时任务
     */
    public void pauseJob(Long jobId) throws Exception {
        Optional<ScheduleJob> job = scheduleJobRepository.findById(jobId);
        if (!job.isPresent()) {
            throw new RuntimeException("任务不存在: " + jobId);
        }

        ScheduleJob scheduleJob = job.get();
        JobKey jobKey = new JobKey(scheduleJob.getJobName(), scheduleJob.getJobGroup());

        scheduler.pauseJob(jobKey);

        scheduleJob.setStatus(JobStatus.PAUSED);
        scheduleJobRepository.save(scheduleJob);

        logger.info("成功暂停定时任务: {}.{}", scheduleJob.getJobGroup(), scheduleJob.getJobName());
    }

    /**
     * 恢复定时任务
     */
    public void resumeJob(Long jobId) throws Exception {
        Optional<ScheduleJob> job = scheduleJobRepository.findById(jobId);
        if (!job.isPresent()) {
            throw new RuntimeException("任务不存在: " + jobId);
        }

        ScheduleJob scheduleJob = job.get();
        JobKey jobKey = new JobKey(scheduleJob.getJobName(), scheduleJob.getJobGroup());

        scheduler.resumeJob(jobKey);

        scheduleJob.setStatus(JobStatus.ACTIVE);
        scheduleJobRepository.save(scheduleJob);

        logger.info("成功恢复定时任务: {}.{}", scheduleJob.getJobGroup(), scheduleJob.getJobName());
    }

    /**
     * 立即执行任务
     */
    public void runJobNow(Long jobId) throws Exception {
        Optional<ScheduleJob> job = scheduleJobRepository.findById(jobId);
        if (!job.isPresent()) {
            throw new RuntimeException("任务不存在: " + jobId);
        }

        ScheduleJob scheduleJob = job.get();
        JobKey jobKey = new JobKey(scheduleJob.getJobName(), scheduleJob.getJobGroup());

        scheduler.triggerJob(jobKey);

        logger.info("立即执行定时任务: {}.{}", scheduleJob.getJobGroup(), scheduleJob.getJobName());
    }

    /**
     * 获取所有任务
     */
    public List<ScheduleJob> getAllJobs() {
        return scheduleJobRepository.findAllActive();
    }

    /**
     * 获取任务详情
     */
    public ScheduleJob getJob(Long jobId) {
        return scheduleJobRepository.findById(jobId).orElse(null);
    }

    /**
     * 创建JobDetail
     */
    private JobDetail createJobDetail(ScheduleJob scheduleJob) throws Exception {
        Class<? extends Job> jobClass = (Class<? extends Job>) Class.forName(scheduleJob.getJobClass());

        JobDataMap jobDataMap = new JobDataMap();
        if (scheduleJob.getJobData() != null && !scheduleJob.getJobData().trim().isEmpty()) {
            Map<String, Object> dataMap = objectMapper.readValue(scheduleJob.getJobData(), Map.class);
            jobDataMap.putAll(dataMap);
        }

        return JobBuilder.newJob(jobClass)
                .withIdentity(scheduleJob.getJobName(), scheduleJob.getJobGroup())
                .withDescription(scheduleJob.getDescription())
                .usingJobData(jobDataMap)
                .storeDurably()
                .build();
    }

    /**
     * 创建Trigger
     */
    private Trigger createTrigger(ScheduleJob scheduleJob) {
        return TriggerBuilder.newTrigger()
                .withIdentity(scheduleJob.getJobName() + "_trigger", scheduleJob.getJobGroup())
                .withSchedule(CronScheduleBuilder.cronSchedule(scheduleJob.getCronExpression()))
                .build();
    }
}
